home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianSliders.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  45KB  |  1,594 lines

  1. /*    ScianSliders.c
  2.     routines for slider-type controls
  3.  
  4.     Jim Lyons
  5.     4/3/91 original version
  6.     5/29/91 EMP removed lib headers
  7.     8/12/91 modified to use ScianFontSystem calls
  8.     8/16/91 modified to use Get/Set2DIntBounds
  9.     9/5/91    added help
  10.     9/27/91    added active/inactive stuff
  11.     10/7/91    removed blind-typing from keydown routine
  12.     10/23/91 fixed exception end-point labeling of scales
  13.     5/20/92 EMP changed ENTERMETHOD to CHANGEDVALUE for slider readout
  14.     5/22/92 EMP changed slider readout to use ParseReal
  15.     5/31/92 EMP fixed / 0 bug in scroll bars
  16. */
  17.  
  18. #include "Scian.h"
  19. #include "ScianTypes.h"
  20. #include "ScianFontSystem.h"
  21. #include "ScianArrays.h"
  22. #include "ScianStyle.h"
  23. #include "ScianColors.h"
  24. #include "ScianIDs.h"
  25. #include "ScianHelp.h"
  26. #include "ScianErrors.h"
  27. #include "ScianControls.h"
  28. #include "ScianWindows.h"
  29. #include "ScianObjWindows.h"
  30. #include "ScianEvents.h"
  31. #include "ScianScripts.h"
  32. #include "ScianMethods.h"
  33. #include "ScianDraw.h"
  34. #include "ScianSliders.h"
  35. #include "ScianScales.h"
  36. #include "ScianTextBoxes.h"
  37. #include "ScianSymbols.h"
  38.  
  39. #define SB_GAP    4
  40. #define MAXNUMWID    37    /*** maximum allowed width of number on scale ***/
  41.  
  42.  
  43. /* bit definitions for highlight of scrollbar parts */
  44. #define THUMBHL    0x01
  45. #define INCRHL    0x02
  46. #define DECRHL    0x04
  47.  
  48. /* repeat time for scroll bar buttons */
  49. #define DELAY    0.2
  50.  
  51. /* EMP static method declarations, NOT prototypes */
  52. static ObjPtr DrawSlider();
  53. static ObjPtr TrackSlider();
  54. static ObjPtr GetVal();
  55. static ObjPtr SetVal();
  56. static ObjPtr SliderKeyProc();
  57. static ObjPtr MakeHelpString();
  58.  
  59.  
  60. ObjPtr sliderClass;
  61.  
  62. void InitSliders()
  63. {
  64.     sliderClass = NewObject(controlClass, 0);
  65.     AddToReferenceList(sliderClass);
  66.     SetVar(sliderClass, NAME, NewString("Slider"));
  67.     SetMethod(sliderClass, DRAW, DrawSlider);
  68.     SetMethod(sliderClass, PRESS, TrackSlider);
  69.     SetMethod(sliderClass, SETVAL, SetVal);
  70.     SetMethod(sliderClass, GETVAL, GetVal);
  71.     SetMethod(sliderClass, KEYDOWN, SliderKeyProc);
  72.     SetMethod(sliderClass, MAKE1HELPSTRING, MakeHelpString);
  73. }
  74.  
  75. void KillSliders()
  76. {
  77.     DeleteThing(sliderClass);
  78. }
  79.  
  80. #ifdef PROTO
  81. ObjPtr NewSlider(int left, int right, int bottom, int top, int style, char *name)
  82. #else
  83. ObjPtr NewSlider(left, right, bottom, top, style, name)
  84. int    left, right, bottom, top, style;
  85. char *name;
  86. #endif
  87. {
  88.     ObjPtr newSlider;
  89.  
  90.     if (left > right)
  91.     {
  92.         register int n;
  93.         n = left; left = right; right = n;
  94.     }
  95.     if (bottom > top)
  96.     {
  97.         register int n;
  98.         n = bottom; bottom = top; top = n;
  99.     }
  100.     newSlider = NewObject(sliderClass, 0);
  101.      
  102.     Set2DIntBounds(newSlider, left, right, bottom, top);
  103.  
  104.     /* set up defaults for slider parameters */
  105.     SetVar(newSlider, STYLE, NewInt(style));
  106.     SetVar(newSlider, NAME, NewString(name));
  107.     SetVar(newSlider, HIGHLIGHTED, NewInt(false));
  108.     SetVar(newSlider, LOVALUE, NewReal(0.0));
  109.     SetVar(newSlider, HIVALUE, NewReal(1.0));
  110.     SetVar(newSlider, STEPVALUE, NewReal(0.1));
  111.     SetVar(newSlider, VALUE, NewReal(0.0));
  112.     SetVar(newSlider, TRACKNOT, NewInt(false));
  113.     SetVar(newSlider, KEYSTRING, NewString("\0"));
  114.     SetVar(newSlider, READOUT, NULLOBJ);
  115.     SetVar(newSlider, TYPESTRING, NewString("slider"));
  116.     SetVar(newSlider, ACTIVATED, ObjTrue);
  117.     switch (style)
  118.     {
  119.     case SCALE:
  120.     case REVSCALE:
  121.         SetVar(newSlider, BIGSTEP, NewReal(0.5));
  122.         SetVar(newSlider, LILSTEP, NewReal(0.1));
  123.         SetVar(newSlider, ANCHOR, NewReal(0.0));
  124.         SetVar(newSlider, FORMAT, NewString("%3.1f"));
  125.         break;
  126.     default:
  127.         SetVar(newSlider, STYLE, NewInt(PLAIN));
  128.         break;
  129.     }
  130.     return newSlider;
  131. }
  132.  
  133. #ifdef PROTO
  134. ObjPtr NewScrollbar(int left, int right, int bottom, int top, char *name)
  135. #else
  136. ObjPtr NewScrollbar(left, right, bottom, top, name)
  137. int    left, right, bottom, top;
  138. char *name;
  139. #endif
  140. {
  141.     ObjPtr newScrollbar;
  142.  
  143.     if (left > right)
  144.     {
  145.         register int n;
  146.         n = left; left = right; right = n;
  147.     }
  148.     if (bottom > top)
  149.     {
  150.         register int n;
  151.         n = bottom; bottom = top; top = n;
  152.     }
  153.     newScrollbar = NewObject(sliderClass, 0);
  154.     Set2DIntBounds(newScrollbar, left, right, bottom, top);
  155.  
  156.     /* set up defaults for scrollbar parameters */
  157.     SetVar(newScrollbar, STYLE, NewInt(SCROLL));
  158.     SetVar(newScrollbar, NAME, NewString(name));
  159.     SetVar(newScrollbar, HIGHLIGHTED, NewInt(0x00)); /* see bit defns */
  160.     SetVar(newScrollbar, LOVALUE, NewReal(0.0));
  161.     SetVar(newScrollbar, HIVALUE, NewReal(1.0));
  162.     SetVar(newScrollbar, STEPVALUE, NewReal(0.1));
  163.     SetVar(newScrollbar, VALUE, NewReal(0.0));
  164.     SetVar(newScrollbar, PORTIONSHOWN, NewReal(1.0));
  165.     SetVar(newScrollbar, TRACKNOT, NewInt(false));
  166.     SetVar(newScrollbar, KEYSTRING, NewString("\0"));
  167.     SetVar(newScrollbar, TYPESTRING, NewString("scrollbar"));
  168.     SetVar(newScrollbar, ACTIVATED, ObjTrue);
  169.     return newScrollbar;
  170. }
  171.  
  172. static ObjPtr MakeHelpString(theSlider, theClass)
  173. ObjPtr theSlider, theClass;
  174. {
  175.     char tempBuf[1000]; /*** fix! ***/
  176.     int style = GetInt(GetVar(theSlider, STYLE));
  177.     if (style == SCROLL)
  178.         strcpy(tempBuf, "To operate the scrollbar, drag the sliding bar with the \
  179. mouse or click in the track to snap it to a new position. Click and hold the arrow \
  180. buttons to scroll automatically. The size of the sliding bar in the control \
  181. relative to the track is proportional to the area being viewed relative to the entire \
  182. scrollable area. If the bar is as long as the track, the entire area is in view and \
  183. the scrollbar does nothing.");
  184.     else
  185.     {
  186.         strcpy(tempBuf, "To operate the slider, drag the pointer \
  187. with the mouse or click in the track to snap it to a new position. After clicking on the \
  188. slider, the arrow keys on the keyboard will also move the pointer. ");
  189.         if (style == SCALE || style == REVSCALE)
  190.             strcat(tempBuf, "The scale shows the range of values possible \
  191. for this slider. Holding the shift key down while dragging the pointer constrains the \
  192. slider to values on the tic marks of the scale. "); /*** fix! ***/
  193.     }
  194.     SetVar(theClass, HELPSTRING, NewString(tempBuf));
  195.     return ObjTrue;
  196. }
  197.  
  198. #ifdef PROTO
  199. void ActivateSlider(ObjPtr slider, Bool act)
  200. #else
  201. void ActivateSlider(slider, act)
  202. ObjPtr slider;
  203. Bool act;
  204. #endif
  205. {
  206.     ObjPtr readout;
  207.     
  208.     if (act == GetPredicate(slider, ACTIVATED)) return; /* activation state unchanged */
  209.     
  210.     if (act)
  211.     {
  212.     SetVar(slider, ACTIVATED, ObjTrue);
  213.     if ( readout = GetVar(slider, READOUT) ) SetVar(readout, ACTIVATED, ObjTrue);
  214.     }
  215.     else
  216.     {
  217.         SetVar(slider, ACTIVATED, ObjFalse);
  218.     if (readout = GetVar(slider, READOUT)) SetVar(readout, ACTIVATED, ObjFalse);
  219.         if (AmICurrent(slider)) MakeMeCurrent(NULLOBJ);
  220.     }
  221.     ImInvalid(slider);
  222. }
  223.  
  224. #ifdef PROTO
  225. void SetTrackNot(ObjPtr theSlider, int value)
  226. #else
  227. void SetTrackNot(theSlider,value)
  228. ObjPtr theSlider;
  229. int value;
  230. #endif
  231. {
  232.     SetVar(theSlider, TRACKNOT, NewInt(value));
  233. }
  234.  
  235. #ifdef PROTO
  236. static void Update(ObjPtr theReadout, real val)
  237. #else
  238. static void Update(theReadout, val)
  239. ObjPtr theReadout;
  240. real val;
  241. #endif
  242. {
  243.     if(logging) InhibitLogging(true);
  244.     if(theReadout)
  245.     {
  246.     /*EMP kluge to prevent infinite loop*/
  247.     FuncTyp method;
  248.     sprintf(tempStr,"%g",val);
  249.     method = GetMethod(theReadout, CHANGEDVALUE);
  250.     SetMethod(theReadout, CHANGEDVALUE, (FuncTyp) 0);
  251.     SetTextBox(theReadout, tempStr);
  252.     SetMethod(theReadout, CHANGEDVALUE, method);
  253. }
  254.     if(logging) InhibitLogging(false);
  255. }
  256.  
  257. static ObjPtr EditSlider(readout)
  258. ObjPtr readout;
  259. {
  260.     ObjPtr slider;
  261.     real val;
  262.  
  263.     if (slider = GetObjectVar("EditSlider", readout, REPOBJ))
  264.     {
  265.     if (logging) InhibitLogging(true);
  266.     strcpy(tempStr, GetString(GetVar(readout, VALUE)));
  267.     if (!ParseReal(&val, tempStr)) /* error in input */
  268.     {
  269.         WarnUser(CW_NUMBERERROR);
  270.         return ObjFalse;
  271.     }
  272.     if (val == missingData)
  273.     {
  274.         WarnUser(CW_MISSINGERROR);
  275.         return ObjFalse;
  276.     }
  277.     if (val >= plusInf || val <= minusInf)
  278.     {
  279.         WarnUser(CW_INFINITYERROR);
  280.         return ObjFalse;
  281.     }
  282.     SetSliderValue(slider, val);
  283.     if (logging) InhibitLogging(false);
  284.     }
  285.     return ObjTrue;
  286. }
  287.  
  288. #ifdef PROTO
  289. ObjPtr SliderReadout(ObjPtr theSlider, ObjPtr theReadout)
  290. #else
  291. ObjPtr SliderReadout(theSlider, theReadout)
  292. ObjPtr theSlider, theReadout;
  293. #endif
  294. {
  295.     SetVar(theSlider, READOUT, theReadout);
  296.     SetVar(theReadout, REPOBJ, theSlider);
  297.     SetMethod(theReadout, CHANGEDVALUE, EditSlider);
  298.     Update(theReadout, GetSliderValue(theSlider));
  299.     return NULLOBJ;
  300. }
  301.  
  302. static ObjPtr GetVal(theSlider)
  303. ObjPtr theSlider;
  304. {
  305.     return GetVar(theSlider, VALUE);
  306. }
  307.  
  308. #ifdef PROTO
  309. real GetSliderValue(ObjPtr theSlider)
  310. #else
  311. real GetSliderValue(theSlider)
  312. ObjPtr theSlider;
  313. #endif
  314. {
  315.     ObjPtr theVal;
  316.  
  317.     theVal = GetVar(theSlider, VALUE);
  318.     if (theVal) return GetReal(theVal);
  319.     else return 0;
  320. }
  321.  
  322. static ObjPtr SetVal(theObj, theVal)
  323. ObjPtr theObj, theVal;
  324. {
  325.     if (!theVal) /* special case: value is NULL */
  326.     {
  327.     SetVar(theObj, VALUE, NULLOBJ);
  328.     return ObjTrue;
  329.     }
  330.     else if (IsReal(theVal)) SetSliderValue(theObj, GetReal(theVal));
  331.     else if (IsInt(theVal)) SetSliderValue(theObj, (real) GetInt(theVal));
  332.     else return ObjFalse; /* error in argument */
  333.     LogControl(theObj);
  334.     return ObjTrue;
  335. }
  336.  
  337. #ifdef PROTO
  338. ObjPtr SetSliderValue(ObjPtr theSlider, real val)
  339. #else
  340. ObjPtr SetSliderValue(theSlider, val)
  341. ObjPtr theSlider;
  342. real val;
  343. #endif
  344. {
  345.     ObjPtr theHiV, theLoV, theStepV;
  346.     ObjPtr theReadout, theStyle, scale;
  347.     real hiVal, loVal, stepVal;
  348.     int style;
  349.  
  350.     if ((theHiV = GetVar(theSlider, VALUE)) && val == GetReal(theHiV)) return ObjFalse; /* no change */
  351.     
  352.     /* sanity check */
  353.     theHiV = GetRealVar("SetSliderValue", theSlider, HIVALUE);
  354.     theLoV = GetRealVar("SetSliderValue", theSlider, LOVALUE);
  355.     theStepV = GetRealVar("SetSliderValue", theSlider, STEPVALUE);
  356.     theStyle = GetIntVar("SetSliderValue", theSlider, STYLE);
  357.     if (!theHiV || !theLoV || !theStepV || !theStyle) return NULLOBJ; /* Yow! Bad. Very bad. */
  358.     hiVal = GetReal(theHiV);
  359.     loVal = GetReal(theLoV);
  360.     stepVal = GetReal(theStepV);
  361.     style = GetInt(theStyle);
  362.     theReadout = GetVar(theSlider, READOUT);
  363.     if ( style != SCROLL && stepVal != 0.0)
  364.     {
  365.     register int n;
  366.     n = 0.5 + val / stepVal;
  367.     val = n * stepVal;
  368.     }
  369.     /* adjust range if value out of it */
  370.     if (val > hiVal)
  371.     {
  372.     SetVar(theSlider, HIVALUE, NewReal(val));
  373.     if (scale = GetVar(theSlider, THESCALE)) SetScaleRange(scale, loVal, val);
  374.     }
  375.     if (val < loVal)
  376.     {
  377.     SetVar(theSlider, LOVALUE, NewReal(val));
  378.     if (scale = GetVar(theSlider, THESCALE)) SetScaleRange(scale, val, hiVal);
  379.     }
  380.     SetVar(theSlider, VALUE, NewReal(val));
  381.     Update(theReadout, val);
  382.     if (style == SCALE || style == REVSCALE)
  383.     {
  384.     int left, right, bottom, top;
  385.  
  386.     Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
  387.     if (right - left < top - bottom)
  388.     /* vertical orientation */
  389.     {
  390.         bottom += VSCALEINSET - CTL_WID/2;
  391.         top -= VSCALEINSET - CTL_WID/2;
  392.         if (style == SCALE)
  393.         ImInvalidBounds(theSlider, 
  394.             left - BIGTICK - 3 - MAXNUMWID, right, bottom, top);
  395.         else ImInvalidBounds(theSlider, left, 
  396.         right + BIGTICK + 3 + MAXNUMWID, bottom, top);
  397.     }
  398.     else /*horizontal*/
  399.     {
  400.         left += HSCALEINSET - CTL_WID/2;
  401.         right -= HSCALEINSET - CTL_WID/2;
  402.         if (style == SCALE)
  403.         ImInvalidBounds(theSlider, left, right,
  404.             bottom, top + BIGTICK + 3 + SCALEFONTSIZE);
  405.         else ImInvalidBounds(theSlider, left, right,
  406.         bottom - BIGTICK - 3 - SCALEFONTSIZE, top);
  407.     }
  408.     }
  409.     else
  410.     {
  411.     ImInvalid(theSlider);
  412.     }
  413. /*** KLUDGE so Eric can speed up drawing ***/
  414.     {
  415.     ObjPtr parent = GetVar(theSlider, PARENT);
  416.     if (parent) ImInvalid(parent);
  417.     }
  418.     ChangedValue(theSlider);
  419.     return ObjTrue;
  420. }
  421.  
  422. #ifdef PROTO
  423. void SetPortionShown(ObjPtr theSlider, real porSh)
  424. #else
  425. void SetPortionShown(theSlider, porSh)
  426. ObjPtr theSlider;
  427. real porSh;
  428. #endif
  429. {
  430.     if (porSh < 0.0) porSh = 0.0;
  431.     
  432.     SetVar(theSlider, PORTIONSHOWN, NewReal(porSh));
  433. }
  434.  
  435. static ObjPtr SliderKeyProc(theSlider, key, flags)
  436. ObjPtr theSlider;
  437. int key;
  438. long flags;
  439. {
  440. #ifdef INTERACTIVE
  441.     ObjPtr theHiV, theLoV, theStepV, theVal, theStyle;
  442.     real hiV, loV, stepV, val;
  443.     int style;
  444.     ObjPtr theReadout;
  445.  
  446.     if(!AmICurrent(theSlider)) return ObjFalse; /* keyboard input not for me */
  447.  
  448.     theHiV = GetRealVar("SliderKeyProc", theSlider, HIVALUE);
  449.     theLoV = GetRealVar("SliderKeyProc", theSlider, LOVALUE);
  450.     theStepV = GetRealVar("SliderKeyProc", theSlider, STEPVALUE);
  451.     theVal= GetRealVar("SliderKeyProc", theSlider, VALUE);
  452.     theStyle = GetIntVar("SliderKeyProc", theSlider, STYLE);
  453.     if (!theHiV || !theLoV || !theStepV || !theVal || !theStyle)
  454.         return ObjTrue;    /* Yow! Bad, wrong, deep doo-doo */
  455.     theReadout = GetVar(theSlider, READOUT);
  456.     hiV = GetReal(theHiV);
  457.     loV = GetReal(theLoV);
  458.     stepV = GetReal(theStepV);
  459.     val = GetReal(theVal);
  460.     style = GetInt(theStyle);
  461.  
  462.     /* process arrow keys only */
  463.     if (key == FK_UP_ARROW || key == FK_RIGHT_ARROW)
  464.     {
  465.     SaveForUndo(theSlider);
  466.     
  467.     /* increment slider value by stepV */
  468.     if (stepV == 0.0) val += (hiV - loV)/100;
  469.     else val += stepV;
  470.     if (val <= hiV) 
  471.     {
  472.         SetVar(theSlider, VALUE, NewReal(val));
  473.         Update(theReadout, val);
  474.         ImInvalid(theSlider);
  475.         ChangedValue(theSlider);
  476.     }
  477.     }
  478.     else if (key == FK_DOWN_ARROW || key == FK_LEFT_ARROW)
  479.     {
  480.     SaveForUndo(theSlider);
  481.     
  482.     /* decrement slider value by stepV */
  483.     if (stepV == 0.0) val -= (hiV - loV)/100;
  484.     else val -= stepV;
  485.     if (val >= loV)
  486.     {
  487.         SetVar(theSlider, VALUE, NewReal(val));
  488.         Update(theReadout, val);
  489.         ImInvalid(theSlider);
  490.         ChangedValue(theSlider);
  491.     }
  492.     }
  493.     else return ObjFalse; /* not one of my keys -- pass it */
  494. #endif
  495.     return ObjTrue;
  496. }
  497.  
  498. #ifdef PROTO
  499. void SetSliderRange(ObjPtr theSlider, real hiVal, real loVal, real stepVal)
  500. #else
  501. void SetSliderRange(theSlider, hiVal, loVal, stepVal)
  502. ObjPtr theSlider;
  503. real hiVal, loVal, stepVal;
  504. #endif
  505. {
  506.     ObjPtr theVal,theStyle;
  507.     real val;
  508.     int style;
  509.     
  510.     theStyle = GetIntVar("SetSliderRange", theSlider, STYLE);
  511.     if (!theStyle) return; /* Yow! */
  512.     style = GetInt(theStyle);
  513.     /* sanity check */
  514.     if (hiVal < loVal)
  515.     {
  516.     real tmp;
  517.     tmp = hiVal; hiVal = loVal; loVal = tmp;
  518.     }
  519.  
  520.     theVal = GetVar(theSlider, VALUE);
  521.     if (theVal)
  522.     {
  523.     val = GetReal(theVal);
  524.     /* adjust range if value if out of range */
  525.     if (val < loVal) loVal = val;
  526.     if (val > hiVal) hiVal = val;
  527.     }
  528.     
  529.     if (stepVal > hiVal - loVal)
  530.     stepVal = hiVal - loVal;
  531.     else if (style != SCROLL && stepVal != 0.0)
  532.     {
  533.     int n;
  534.     n = ((hiVal - loVal) / stepVal) + 0.5;
  535.     hiVal = n * stepVal + loVal;
  536.     }
  537.     SetVar(theSlider, HIVALUE, NewReal(hiVal));
  538.     SetVar(theSlider, LOVALUE, NewReal(loVal));
  539.     SetVar(theSlider, STEPVALUE, NewReal(stepVal));
  540.     if (style == SCALE || style == REVSCALE)
  541.     {
  542.     int left, right, bottom, top;
  543.     ObjPtr scale;
  544.  
  545.     if (scale = GetVar(theSlider, THESCALE))
  546.     {
  547.         SetScaleRange(scale, loVal, hiVal);
  548.     }
  549.     else
  550.     {
  551.  
  552.         Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
  553.         if (right - left < top - bottom)
  554.         /* vertical orientation */
  555.         {
  556.         bottom += VSCALEINSET - CTL_WID/2;
  557.         top -= VSCALEINSET - CTL_WID/2;
  558.         if (style == SCALE) ImInvalidBounds(theSlider, 
  559.           left - BIGTICK - 3 - MAXNUMWID, right, bottom, top);
  560.         else ImInvalidBounds(theSlider, left, 
  561.           right + BIGTICK + 3 + MAXNUMWID, bottom, top);
  562.         }
  563.         else /*horizontal*/
  564.         {
  565.         left += HSCALEINSET - CTL_WID/2;
  566.         right -= HSCALEINSET - CTL_WID/2;
  567.         if (style == SCALE) ImInvalidBounds(theSlider, left,
  568.           right, bottom, top + BIGTICK + 3 + SCALEFONTSIZE);
  569.         else ImInvalidBounds(theSlider, left, right,
  570.           bottom - BIGTICK - 3 - SCALEFONTSIZE, top);
  571.         }
  572.     }
  573.     }
  574.     else
  575.     {
  576.     ImInvalid(theSlider);
  577.     }
  578. /*** KLUDGE so Eric can speed up drawing ***/
  579.     {
  580.     ObjPtr parent = GetVar(theSlider, PARENT);
  581.     if (parent) ImInvalid(parent);
  582.     }
  583. }
  584.  
  585. #ifdef PROTO
  586. void SetSliderScale(ObjPtr theSlider, real bigStep, real lilStep, real anchor, char *format)
  587. #else
  588. void SetSliderScale(theSlider, bigStep, lilStep, anchor, format)
  589. ObjPtr theSlider;
  590. real bigStep, lilStep, anchor;
  591. char *format;
  592. #endif
  593. {
  594.     SetVar(theSlider, BIGSTEP, NewReal(bigStep));
  595.     SetVar(theSlider, LILSTEP, NewReal(lilStep));
  596.     SetVar(theSlider, ANCHOR, NewReal(anchor));
  597.     SetVar(theSlider, FORMAT, NewString(format));
  598. }
  599.  
  600. static ObjPtr DrawSlider(theSlider)
  601. ObjPtr    theSlider;
  602. {
  603. #ifdef GRAPHICS
  604.     int cp,cl,sl;
  605.     int wid;
  606.     Coord x[3][2];
  607.     ObjPtr theHiV, theLoV, theStepV, theVal, theHilite, theStyle, thePorSh;
  608.     ObjPtr theBigStep, theLilStep, theAnchor, theFormat;
  609.     int left, right, bottom, top, style;
  610.     int i, j, nl, nh, m;
  611.     int active, highlight;
  612.     Bool nullV;
  613.     real hiV, loV, stepV, val, porSh, bigStep, lilStep, anchorV, sV, siz, r;
  614.     real anchorC, hiC, loC;    /* Coordinate of scale hi, lo, and anchor point */
  615.     real minC = -1e6, maxC = 0; /*** don't ask... */
  616.     char *format, theNumber[10];
  617.  
  618.     Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
  619.  
  620.     /* get the style and value parameters */
  621.     theHiV = GetRealVar("DrawSlider", theSlider, HIVALUE);
  622.     theLoV = GetRealVar("DrawSlider", theSlider, LOVALUE);
  623.     theStepV = GetRealVar("DrawSlider", theSlider, STEPVALUE);
  624.     theHilite = GetIntVar("DrawSlider", theSlider, HIGHLIGHTED);
  625.     theStyle = GetIntVar("DrawSlider", theSlider, STYLE);
  626.     if (!theHiV || !theLoV || !theStepV || !theHilite || !theStyle)
  627.         return NULLOBJ;    /* Yow! Bad, wrong, doo-doo */
  628.     hiV = GetReal(theHiV);
  629.     loV = GetReal(theLoV);
  630.     stepV = GetReal(theStepV);
  631.     if ( theVal = GetVar(theSlider, VALUE) ) val = GetReal(theVal);
  632.     
  633.     highlight = GetInt(theHilite);
  634.     active = GetPredicate(theSlider, ACTIVATED);
  635.     style = GetInt(theStyle);
  636.     switch (style)
  637.     {
  638.     case PLAIN:
  639.         break;
  640.  
  641.     case SCALE:
  642.     case REVSCALE:
  643.         theBigStep = GetRealVar("DrawSlider", theSlider, BIGSTEP);
  644.         theLilStep = GetRealVar("DrawSlider", theSlider, LILSTEP);
  645.         theAnchor = GetRealVar("DrawSlider", theSlider, ANCHOR);
  646.         theFormat = GetStringVar("DrawSlider", theSlider, FORMAT);
  647.         if (!theBigStep || !theLilStep || !theAnchor || !theFormat)
  648.             return NULLOBJ;    /* Yow! Missing things! */
  649.         bigStep = GetReal(theBigStep);
  650.         lilStep = GetReal(theLilStep);
  651.         anchorV = GetReal(theAnchor);
  652.         format = GetString(theFormat);
  653.         SetupFont("Helvetica", SCALEFONTSIZE); /***/
  654.         break;
  655.  
  656.     case SCROLL:
  657.         thePorSh = GetRealVar("DrawSlider", theSlider, PORTIONSHOWN);
  658.         if (thePorSh) porSh = GetReal(thePorSh);
  659.         else return NULLOBJ; /* Yow! Something's rong */
  660.         /* normalize portion shown */
  661.         porSh = porSh/(porSh + hiV - loV);
  662.         break;
  663.  
  664.     default:
  665.         style = PLAIN;
  666.         SetVar(theSlider, STYLE, NewInt(PLAIN));
  667.         break;
  668.     }
  669.  
  670.     /* so draw it already */
  671.     if (right - left > top - bottom)
  672.     {
  673.     /* horizontal orientation */
  674.     cl = (bottom + top) / 2;
  675.     switch(style)
  676.     {
  677.         case SCALE:
  678.         left += HSCALEINSET - CTL_WID/2;
  679.         right -= HSCALEINSET - CTL_WID/2;
  680.         if (IsDrawingRestricted(left, right, bottom,
  681.            top + BIGTICK + 3 + SCALEFONTSIZE)) return ObjFalse;
  682.         DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
  683.             active ? UIPGREEN : UIBACKGROUND);
  684.         loC = left + CTL_WID/2;
  685.         hiC = right - CTL_WID/2;
  686.         r = (hiC - loC) / (hiV - loV);
  687.         anchorC = loC + r*(anchorV - loV);
  688.         sl = top;
  689.         if (theVal)
  690.         {
  691.             cp = loC + r*(val - loV) + 0.5;
  692.             DrawCtlUp(cp-CTL_WID/2, cp+CTL_WID/2, bottom, sl-2,
  693.                 highlight ? UIHIBACKGROUND : UIBACKGROUND);
  694.         }
  695.     /***/    if (GetVar(theSlider, THESCALE)) break;
  696.     /***/    printf("Old style scale on slider %s\n", GetString(GetVar(theSlider, NAME)));
  697.         
  698.         /* draw scale over slider */
  699.         SetUIColor(active ? UITEXT : UIGREYTEXT);
  700.         DrawLine(loC, sl, hiC, sl);
  701.         nl = (loV - anchorV)/bigStep - 1;
  702.         nh = (hiV - anchorV)/bigStep + 1;
  703.         for (i=nl; i<=nh; ++i)
  704.         {
  705.             sV = i*bigStep + anchorV; /* starting value for each step */
  706.             if (sV >= loV && sV <= hiV)
  707.             {
  708.             int u = anchorC + r*(sV - anchorV) + 0.5;
  709.             DrawLine(u, sl, u, sl + BIGTICK);
  710.  
  711.             /* draw number next to tick */
  712.             sprintf(theNumber, format, sV);
  713.             DrawAString(CENTERALIGN, u, sl + BIGTICK + 3, theNumber);
  714.  
  715.             /* remember min and max coord of labels */
  716.             if (minC < -1e5) minC = u - wid/2;
  717.             maxC = u + wid/2;
  718.             }
  719.             if (i == nh) break;
  720.             m = bigStep/lilStep + 0.5;
  721.             for (j=1; j<m; ++j)
  722.             {
  723.             int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
  724.             if (u > hiC + 1) break;
  725.             if (u >= loC) 
  726.             {
  727.                 DrawLine(u, sl, u, sl + LILTICK);
  728.             }
  729.             }
  730.         }
  731.         /* check if end points need labels */
  732.         sprintf(theNumber, format, loV);
  733.         wid = StrWidth(theNumber);
  734.         if (loC + wid/2 < minC) /* label low end of scale */
  735.         {
  736.             DrawAString(CENTERALIGN, loC, sl + BIGTICK + 3, theNumber);
  737.         }
  738.         sprintf(theNumber, format, hiV);
  739.         wid = StrWidth(theNumber);
  740.         if (hiC - wid/2 > maxC) /* label high end of scale */
  741.         {
  742.             DrawAString(CENTERALIGN, hiC, sl + BIGTICK + 3, theNumber);
  743.         }
  744.         break;
  745. #if 0
  746.         case REVSCALE:
  747.         left += HSCALEINSET - CTL_WID/2;
  748.         right -= HSCALEINSET - CTL_WID/2;
  749.         if (IsDrawingRestricted(left, right,
  750.            bottom - BIGTICK + 3 + SCALEFONTSIZE, top)) return ObjFalse;
  751.         DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
  752.             active ? UIPGREEN : UIBACKGROUND);
  753.         loC = left + CTL_WID/2;
  754.         hiC = right - CTL_WID/2;
  755.         r = (hiC - loC) / (hiV - loV);
  756.         anchorC = loC + r*(anchorV - loV);
  757.         cp = loC + r*(val - loV) + 0.5;
  758.         /* draw scale under slider */
  759.         sl = bottom;
  760.         SetUIColor(active ? UITEXT : UIGREYTEXT);
  761.         DrawLine(loC, sl, hiC, sl);
  762.         nl = (loV - anchorV)/bigStep - 1;
  763.         nh = (hiV - anchorV)/bigStep + 1;
  764.         for (i=nl; i<=nh; ++i)
  765.         {
  766.             sV = i*bigStep + anchorV;    /* "starting" value for each step */
  767.             if (sV >= loV && sV <= hiV)
  768.             {
  769.             int u = anchorC + r*(sV - anchorV) + 0.5;
  770.             DrawLine(u, sl, u, sl - BIGTICK);
  771.  
  772.             /* draw number next to tick */
  773.             sprintf(theNumber, format, sV);
  774.             DrawAString(CENTERALIGN, u, sl - BIGTICK - 3, theNumber);
  775.             }
  776.             if (i == nh) break;
  777.             m = bigStep/lilStep + 0.5;
  778.             for (j=1; j<m; ++j)
  779.             {
  780.             int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
  781.             if (u > hiC) break;
  782.             if (u >= loC)
  783.             {
  784.                 DrawLine(u, sl, u, sl - LILTICK);
  785.             }
  786.             }
  787.         }
  788.         DrawCtlDown(cp-CTL_WID/2, cp+CTL_WID/2, sl+2, top,
  789.             highlight ? UIHIBACKGROUND : UIBACKGROUND);
  790.         break;
  791. #endif
  792.         case SCROLL:
  793.         if (IsDrawingRestricted(left, right, bottom, 
  794.             top))
  795.         {
  796.             return ObjFalse;
  797.         }
  798.  
  799.         wid = top - bottom;
  800.         loC = left + wid + EDGE + SB_GAP;
  801.         hiC = right - wid - EDGE - SB_GAP;
  802.         siz = (hiC - loC)*porSh;    /* size of thumb */
  803.         if (siz < wid) siz = wid;    /* min size is square */
  804.         hiC -= siz; /* lower limit of posn of thumb */
  805.         if (hiV <= loV) sV = loC;
  806.         else sV = loC + (val-loV)*(hiC - loC)/(hiV - loV) + 0.5;
  807.         /* draw left-button */
  808.         DrawRaisedRect(left, left+wid, bottom, top, 
  809.             DECRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  810.         /* (draw left arrow on top) */
  811.         FillUITri(left + 0.28*wid, cl,
  812.             left + 0.61*wid, cl - wid/3,
  813.             left + 0.61*wid,cl + wid/3,
  814.             active ? UITEXT : UIGREYTEXT);
  815.  
  816.         /* draw right-button */
  817.         DrawRaisedRect(right-wid, right, bottom, top, 
  818.             INCRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  819.         /* (draw right arrow on top) */
  820.         FillUITri(right - 0.28*wid, cl,
  821.             right - 0.61*wid, cl - wid/3,
  822.             right - 0.61*wid, cl + wid/3,
  823.             active ? UITEXT : UIGREYTEXT);
  824.  
  825.         /* draw track */
  826.         DrawSunkenRect(left+wid+SB_GAP, right-wid-SB_GAP, bottom, top,
  827.             active ? UIPGREEN : UIBACKGROUND);
  828.  
  829.         /* draw thumb */
  830.         DrawRaisedRect(sV, sV+siz, bottom+EDGE, top-EDGE,
  831.             THUMBHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  832.         break;
  833.  
  834.         case PLAIN:
  835.         default:
  836.         if (IsDrawingRestricted(left, right, bottom, 
  837.             top)) return ObjFalse;
  838.         DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
  839.             active ? UIPGREEN : UIBACKGROUND);
  840.         loC = left + CTL_WID/2;
  841.         hiC = right - CTL_WID/2;
  842.         r = (hiC - loC) / (hiV - loV);
  843.         if (theVal)
  844.         {
  845.             cp = loC + r*(val - loV) + 0.5;
  846.             DrawRaisedRect(cp-CTL_WID/2, cp+CTL_WID/2, bottom, top,
  847.                 highlight ? UIHIBACKGROUND : UIBACKGROUND);
  848.         }
  849.         break;
  850.     }
  851.     }
  852.     else
  853.     {
  854.     /* vertical orientation */
  855.     cl = (left + right)/2;
  856.     switch(style)
  857.     {
  858.         case SCALE:
  859.         bottom += VSCALEINSET - CTL_WID/2;
  860.         top -= VSCALEINSET - CTL_WID/2;
  861.         if (IsDrawingRestricted(left - BIGTICK - 3 - MAXNUMWID, right,
  862.             bottom, top)) return ObjFalse;
  863.         DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
  864.             active ? UIPGREEN : UIBACKGROUND);
  865.         loC = bottom + CTL_WID/2;
  866.         hiC = top - CTL_WID/2;
  867.         r = (hiC - loC)/(hiV - loV);
  868.         anchorC = r*(anchorV - loV) + loC;
  869.         sl = left;
  870.         if (theVal)
  871.         {
  872.             cp = loC + r*(val-loV) + 0.5;
  873.             DrawCtlLeft(sl+2, right, cp-CTL_WID/2, cp+CTL_WID/2, 
  874.                 highlight ? UIHIBACKGROUND : UIBACKGROUND);
  875.         }
  876.     /***/    if (GetVar(theSlider, THESCALE)) break;
  877.     /***/    printf("Old style scale on slider %s\n", GetString(GetVar(theSlider, NAME)));
  878.         
  879.         /* draw scale on left of slider */
  880.         SetUIColor(active ? UITEXT : UIGREYTEXT);
  881.         DrawLine(sl, loC, sl, hiC);
  882.         nl = (loV - anchorV)/bigStep - 1;
  883.         nh = (hiV - anchorV)/bigStep + 1;
  884.         for (i=nl; i<=nh; ++i)
  885.         {
  886.             sV = i*bigStep + anchorV; /* starting value for each step */
  887.             if (sV >= loV && sV <= hiV)
  888.             {
  889.             int u = anchorC + r*(sV - anchorV) + 0.5;
  890.             DrawLine(sl, u, sl - BIGTICK, u);
  891.  
  892.             /* draw number next to tick */
  893.             sprintf(theNumber, format, sV);
  894.             DrawAString(RIGHTALIGN, sl - BIGTICK - 3, u - 3, theNumber);
  895.  
  896.             /* remember min and max coords of labels */
  897.             if (minC < -1e5) minC = u - 3;
  898.             maxC = u - 3 + SCALEFONTSIZE;
  899.             }
  900.             if (i == nh) break;
  901.             m = bigStep/lilStep + 0.5;
  902.             for (j=1; j<m; ++j)
  903.             {
  904.             int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
  905.             if (u > hiC + 1) break;
  906.             if (u >= loC)
  907.             {
  908.                 DrawLine(sl, u, sl - LILTICK, u);
  909.             }
  910.             }
  911.         }
  912.         /* check if end points need labels */
  913.         sprintf(theNumber, format, loV);
  914.         wid = StrWidth(theNumber);
  915.         if (loC - 3 + SCALEFONTSIZE < minC) /* label low end of scale */
  916.         {
  917.             DrawAString(RIGHTALIGN, sl - BIGTICK - 3, loC - 3, theNumber);
  918.         }
  919.         if (hiC - 3 > maxC) /* label high end of scale */
  920.         {
  921.             sprintf(theNumber, format, hiV);
  922.             wid = StrWidth(theNumber);
  923.             DrawAString(RIGHTALIGN, sl - BIGTICK - 3, hiC - 3, theNumber);
  924.         }
  925.         break;
  926. #if 0
  927.         case REVSCALE:
  928.         bottom += VSCALEINSET - CTL_WID/2;
  929.         top -= VSCALEINSET - CTL_WID/2;
  930.         if (IsDrawingRestricted(left, right + BIGTICK + 3 + MAXNUMWID,
  931.             bottom, top)) return ObjFalse;
  932.         DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
  933.             active ? UIPGREEN : UIBACKGROUND);
  934.         loC = bottom + CTL_WID/2;
  935.         hiC = top - CTL_WID/2;
  936.         r = (hiC - loC)/(hiV - loV);
  937.         anchorC = r*(anchorV - loV) + loC;
  938.         cp = loC + r*(val-loV) + 0.5;
  939.         /* draw scale on right of slider */
  940.         sl = right;
  941.         SetUIColor(active ? UITEXT : UIGREYTEXT);
  942.         DrawLine(sl, loC, sl, hiC);
  943.         nl = (loV - anchorV)/bigStep - 1;
  944.         nh = (hiV - anchorV)/bigStep + 1;
  945.         for (i=nl; i<=nh; ++i)
  946.         {
  947.             sV = i*bigStep + anchorV;    /* "starting" value for each step */
  948.             if (sV >= loV && sV <= hiV)
  949.             {
  950.             int u = anchorC + r*(sV - anchorV) + 0.5;
  951.             DrawLine(sl, u, sl + BIGTICK, u);
  952.  
  953.             /* draw number next to tick */
  954.             sprintf(theNumber, format, sV);
  955.             wid = StrWidth(theNumber);
  956.             DrawAString(LEFTALIGN, sl + BIGTICK + 3, u - 3, theNumber);
  957.             }
  958.             if (i == nh) break;
  959.             m = bigStep/lilStep + 0.5;
  960.             for (j=1; j<m; ++j)
  961.             {
  962.             int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
  963.             if (u > hiC) break;
  964.             if (u >= loC)
  965.             {
  966.                 DrawLine(sl, u, sl + LILTICK, u);
  967.             }
  968.             }
  969.         }
  970.         DrawCtlRight(left, sl-2, cp-CTL_WID/2, cp+CTL_WID/2, 
  971.             highlight ? UIHIBACKGROUND : UIBACKGROUND);
  972.         break;
  973. #endif
  974.         case SCROLL:
  975.         if (IsDrawingRestricted(left, right, bottom, 
  976.             top))
  977.         {
  978.             return ObjFalse;
  979.         }
  980.  
  981.         wid = right - left;
  982.         loC = bottom + wid + EDGE + SB_GAP;
  983.         hiC = top - wid - EDGE - SB_GAP;
  984.         siz = (hiC - loC)*porSh; /* size of thumb */
  985.         if (siz < wid) siz = wid;    /* min size is square */
  986.         hiC -= siz; /* limit position of thumb */
  987.         if (hiV == loV) sV = loC;
  988.         else sV = loC + (val-loV)*(hiC - loC)/(hiV - loV) + 0.5;
  989.         /* draw up-button */
  990.         DrawRaisedRect(left, right, top - wid, top, 
  991.             INCRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  992.         /* (draw up arrow on top) */
  993.         FillUITri(cl, top - 0.28*wid,
  994.             cl - wid/3, top - 0.61*wid,
  995.             cl + wid/3, top - 0.61*wid,
  996.             active ? UITEXT : UIGREYTEXT);
  997.  
  998.         /* draw down-button */
  999.         DrawRaisedRect(left, right, bottom, bottom + wid, 
  1000.             DECRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  1001.         /* (draw down arrow on top) */
  1002.         FillUITri(cl, bottom + 0.28*wid,
  1003.             cl - wid/3, bottom + 0.61*wid,
  1004.             cl + wid/3, bottom + 0.61*wid,
  1005.             active ? UITEXT : UIGREYTEXT);
  1006.  
  1007.         /* draw track */
  1008.         DrawSunkenRect(left, right, bottom + wid + SB_GAP, top - wid - SB_GAP,
  1009.             active ? UIPGREEN : UIBACKGROUND);
  1010.         /* draw thumb */
  1011.         DrawRaisedRect(left + EDGE, right - EDGE, sV, sV + siz,
  1012.              THUMBHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
  1013.         break;
  1014.  
  1015.         case PLAIN:
  1016.         default:
  1017.         if (IsDrawingRestricted(left, right, bottom, 
  1018.             top)) return ObjFalse;
  1019.         DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
  1020.             active ? UIPGREEN : UIBACKGROUND);
  1021.         loC = bottom + CTL_WID/2;
  1022.         hiC = top - CTL_WID/2;
  1023.         r = (hiC - loC)/(hiV - loV);
  1024.         if (theVal)
  1025.         {
  1026.             cp = loC + r*(val-loV) + 0.5;
  1027.             DrawRaisedRect(left, right, cp-CTL_WID/2, cp+CTL_WID/2,
  1028.                 highlight ? UIHIBACKGROUND : UIBACKGROUND);
  1029.         }
  1030.         break;
  1031.     }
  1032.     }
  1033.     if (!active) FillUIGauzeRect(left, right, bottom, top, UIBACKGROUND);
  1034. #endif
  1035.     return NULLOBJ;
  1036. }
  1037.  
  1038. static ObjPtr TrackSlider(theSlider, mouseX, mouseY, flags)
  1039. ObjPtr theSlider;
  1040. int mouseX, mouseY;
  1041. long flags;
  1042. {
  1043. #ifdef INTERACTIVE
  1044.     int left, right, bottom, top, cp;
  1045.     ObjPtr theHiV, theLoV, theStepV, theLilStep;
  1046.     int style, mX, mY, offset;
  1047.     real hiV, loV, stepV, val, curVal, lilStep, valSave;
  1048.     ObjPtr theStyle, theValue;
  1049.     ObjPtr theReadout;
  1050.     struct tms tbuf;
  1051.     long prevTime = 0L;
  1052.     Bool hilit = false, tracking;
  1053.  
  1054.     Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
  1055.  
  1056.     /* return if mouse outside slider rectangle */
  1057.     if (mouseX < left - 1 || mouseX > right + 1 || mouseY < bottom -1
  1058.             || mouseY > top + 1) return ObjFalse;
  1059.     if (TOOL(flags) == T_HELP)
  1060.     {
  1061.     ContextHelp(theSlider);
  1062.     return ObjTrue;
  1063.     }
  1064.  
  1065.     /* return if not active or has null value */
  1066.     if (!GetPredicate(theSlider, ACTIVATED)
  1067.     || !(theValue = GetVar(theSlider, VALUE))) return ObjTrue;
  1068.  
  1069.     MakeMeCurrent(theSlider); /* make slider current for keyboard input */
  1070.  
  1071.     SaveForUndo(theSlider);
  1072.  
  1073.     /* get range and value of slider */
  1074.     theHiV = GetRealVar("TrackSlider", theSlider, HIVALUE);
  1075.     theLoV = GetRealVar("TrackSlider", theSlider, LOVALUE);
  1076.     theStepV = GetRealVar("TrackSlider", theSlider, STEPVALUE);
  1077.     theStyle = GetIntVar("TrackSlider", theSlider, STYLE);
  1078.     if (!theHiV || !theLoV || !theStepV || !theStyle) return ObjTrue; /* Yow! */
  1079.     hiV = GetReal(theHiV);
  1080.     loV = GetReal(theLoV);
  1081.     stepV = GetReal(theStepV);
  1082.     curVal = valSave = val = GetReal(theValue);
  1083.     theReadout = GetVar(theSlider, READOUT);
  1084.     tracking = !GetPredicate(theSlider, TRACKNOT) && !(flags & F_OPTIONDOWN);
  1085.     style = GetInt(theStyle);
  1086.     if (style == SCALE || style == REVSCALE) 
  1087.     {
  1088.     ObjPtr valArray, scale;
  1089.     real *p;
  1090.     
  1091.     if (scale = GetVar(theSlider, THESCALE))
  1092.     {
  1093.         valArray = GetVar(scale, VALUE);
  1094.         p = ELEMENTS(valArray);
  1095.         lilStep = p[2]/p[3];
  1096.     }
  1097.     else
  1098.     {
  1099.         theLilStep = GetRealVar("TrackSlider", theSlider, LILSTEP);
  1100.         if (theLilStep) lilStep = GetReal(theLilStep);
  1101.         else lilStep = 0;
  1102.     }
  1103.     }
  1104.     if (right - left > top - bottom)
  1105.     {
  1106.     /* horizontal orientation */
  1107.     if (style == SCROLL)
  1108.     {
  1109.         int wid = top - bottom;
  1110.     
  1111.         /* which part is mouse in? */
  1112.         if (mouseX > left && mouseX < left + wid) /* decr button */
  1113.         {
  1114.             /* follow mouse */
  1115.             while (Mouse(&mX, &mY))
  1116.             {
  1117.                 if (mX < left - SLOP || mX > left + wid + SLOP
  1118.                     || mY < bottom - SLOP || mY > top + SLOP)
  1119.                 {
  1120.                     /* outside slop rect */
  1121.                     if (!hilit) continue;
  1122.                     SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1123.                     DrawMe(theSlider);
  1124.                     hilit = false;
  1125.                 }
  1126.                 else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
  1127.                 {
  1128.                     /* decrement val by stepV */
  1129.                     prevTime = times(&tbuf);
  1130.                     if ((val -= stepV) < loV) val = loV;
  1131.                     if (!hilit || val != curVal)
  1132.                     {
  1133.                         SetVar(theSlider, VALUE, NewReal(val));
  1134.                         SetVar(theSlider, HIGHLIGHTED, NewInt(DECRHL));
  1135.                         DrawMe(theSlider);
  1136.                         if (tracking) ChangedValue(theSlider);
  1137.                         curVal = val;
  1138.                         hilit = true;
  1139.                     }
  1140.                 }
  1141.             }
  1142.         }
  1143.         else if (mouseX < right && mouseX > right - wid) /* incr button */
  1144.         {
  1145.             /* follow mouse */
  1146.             while (Mouse(&mX, &mY))
  1147.             {
  1148.                 if (mX < right - wid - SLOP || mX > right + SLOP
  1149.                     || mY < bottom - SLOP || mY > top + SLOP)
  1150.                 {
  1151.                     /* outside slop rect */
  1152.                     if (!hilit) continue;
  1153.                     SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1154.                     DrawMe(theSlider);
  1155.                     hilit = false;
  1156.                 }
  1157.                 else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
  1158.                 {
  1159.                     /* increment val by stepV */
  1160.                     prevTime = times(&tbuf);
  1161.                     if ((val += stepV) > hiV) val = hiV;
  1162.                     if (!hilit || val != curVal)
  1163.                     {
  1164.                         SetVar(theSlider, VALUE, NewReal(val));
  1165.                         SetVar(theSlider, HIGHLIGHTED, NewInt(INCRHL));
  1166.                         DrawMe(theSlider);
  1167.                         if (tracking) ChangedValue(theSlider);
  1168.                         curVal = val;
  1169.                         hilit = true;
  1170.                     }
  1171.                 }
  1172.             }
  1173.         }
  1174.         else /* track or thumb */
  1175.         {
  1176.             ObjPtr thePorSh;
  1177.             real porSh, loC, hiC, siz, posn;
  1178.     
  1179.             thePorSh = GetRealVar("TrackSlider", theSlider, PORTIONSHOWN);
  1180.             if (thePorSh) porSh = GetReal(thePorSh);
  1181.             else return ObjTrue; /* Yow! Oh, well. */
  1182.             /* normalize portion shown */
  1183.             porSh = porSh/(porSh + hiV - loV);
  1184.             loC = left + wid + EDGE + SB_GAP;
  1185.             hiC = right - wid - EDGE - SB_GAP;
  1186.             siz = porSh*(hiC - loC);
  1187.             if (siz < wid) siz = wid; /* min size */
  1188.             hiC -= siz; /* max posn of thumb */
  1189.             if (hiV <= loV) posn = loC;
  1190.             else posn = (hiC - loC)*(val - loV)/(hiV - loV) + loC;
  1191.             if (mouseX < posn || mouseX > posn + siz) /* in track */
  1192.             {
  1193.                 /* jump thumb to click position, then follow */
  1194.                 offset = -siz/2;
  1195.                 if (hiC <= loC)
  1196.                 {
  1197.                 val = loV;
  1198.                 }
  1199.                 else
  1200.                 {
  1201.                 val = loV + (hiV - loV)*(mouseY + offset - loC)/(hiC - loC);
  1202.                 }
  1203.                 if (val < loV) val = loV;
  1204.                 else if (val > hiV) val = hiV;
  1205.                 SetVar(theSlider, VALUE, NewReal(curVal = val));
  1206.             }
  1207.             else offset = posn - mouseX;
  1208.             SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
  1209.             DrawMe(theSlider);
  1210.             /* now follow mouse with thumb */
  1211.             while (Mouse(&mX, &mY))
  1212.             {
  1213.                 if (mX < left + wid - SLOP || mX > right - wid + SLOP
  1214.                     || mY < bottom - SLOP || mY > top + SLOP)
  1215.                 {
  1216.                     /* outside slop rect */
  1217.                     if (hilit)
  1218.                     {
  1219.                         SetVar(theSlider, VALUE, theValue);
  1220.                         SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1221.                         DrawMe(theSlider);
  1222.                         if (tracking) ChangedValue(theSlider);
  1223.                         curVal = val = valSave;
  1224.                         hilit = false;
  1225.                     }
  1226.                     if (!Mouse(&mX, &mY)) break;
  1227.                 }
  1228.                 else
  1229.                 {
  1230.                     /* follow with thumb */
  1231.                     if (hiC <= loC)
  1232.                     {
  1233.                     val = loV;
  1234.                     }
  1235.                     else
  1236.                     {
  1237.                     val = loV + (hiV - loV)*(mX + offset - loC)/(hiC - loC);
  1238.                     }
  1239.                     if (val < loV) val = loV;
  1240.                     else if (val > hiV) val = hiV;
  1241.                     if (!hilit || val != curVal)    /* value has changed */
  1242.                     {
  1243.                         SetVar(theSlider, VALUE, NewReal(val));
  1244.                         SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
  1245.                         DrawMe(theSlider);
  1246.                         if (tracking) ChangedValue(theSlider);
  1247.                         curVal = val;    /* remember current value */
  1248.                         hilit = true;
  1249.                     }
  1250.                 }
  1251.             }
  1252.         }
  1253.     }
  1254.     else /* not a scrollbar */
  1255.     {
  1256.         if (style == SCALE || style == REVSCALE) /* adjust bounds */
  1257.         {
  1258.         left += HSCALEINSET - CTL_WID/2;
  1259.         right -= HSCALEINSET - CTL_WID/2;
  1260.         }
  1261.         cp = ((val-loV)/(hiV - loV))*(right - left - CTL_WID)
  1262.                 + left + CTL_WID/2;
  1263.         if (mouseX < cp - CTL_WID/2 - 1 || mouseX > cp + CTL_WID/2 + 1)
  1264.         {
  1265.             /* click in track; jump control to click position */
  1266.             offset = 0;
  1267.             val = loV + (hiV - loV)*
  1268.              (mouseX - left - CTL_WID/2)/(right - left - CTL_WID);
  1269.             if (val < loV) val = loV;
  1270.             else if (val > hiV) val = hiV;
  1271.             else if (stepV != 0.0)
  1272.             {
  1273.                 int n;
  1274.                 n = 0.5 + (val - loV)/stepV;
  1275.                 val = loV + n*stepV;
  1276.             }
  1277.             if (flags & F_CONSTRAIN && (style == SCALE || style == REVSCALE)
  1278.             && lilStep != 0)
  1279.             {
  1280.             /* constrain value to little steps of scale */
  1281.             int n;
  1282.             n = 0.5 + val/lilStep;
  1283.             val = n*lilStep;
  1284.             }
  1285.             SetVar(theSlider, VALUE, NewReal(curVal = val));
  1286.         }
  1287.         else offset = cp - mouseX;
  1288.     
  1289.         /* now follow the mouse */
  1290.         while (Mouse(&mX, &mY))
  1291.         {
  1292.             if (mX < left - SLOP || mX > right + SLOP
  1293.                 || mY < bottom - SLOP || mY > top + SLOP)
  1294.             {
  1295.                 /* outside slop rect */
  1296.                 if (hilit)
  1297.                 {
  1298.                     SetVar(theSlider, VALUE, theValue);
  1299.                     SetVar(theSlider, HIGHLIGHTED, NewInt(false));
  1300.                     Update(theReadout, valSave);
  1301.                     DrawMe(theSlider);
  1302.                     if (tracking) ChangedValue(theSlider);
  1303.                     curVal = val = valSave;
  1304.                     hilit = false;
  1305.                 }
  1306.                 if (!Mouse(&mX, &mY)) break;
  1307.             }
  1308.             else
  1309.             {
  1310.                 /* follow mouse with slider */
  1311.                 val = loV + (hiV - loV)*
  1312.                   (mX + offset - left - CTL_WID/2)/(right - left - CTL_WID);
  1313.                 if (val < loV) val = loV;
  1314.                 else if (val > hiV) val = hiV;
  1315.                 else if (stepV != 0.0)
  1316.                 {
  1317.                     int n;
  1318.                     n = 0.5 + val/stepV;
  1319.                     val = n*stepV;
  1320.                 }
  1321.                 else if (flags & F_CONSTRAIN && 
  1322.                     (style == SCALE || style == REVSCALE) && lilStep != 0)
  1323.                 {
  1324.                     /* constrain value to little steps of scale */
  1325.                     int n;
  1326.                     n = 0.5 + val/lilStep;
  1327.                     val = n*lilStep;
  1328.                 }
  1329.                 if (!hilit || val != curVal)
  1330.                 {
  1331.                     SetVar(theSlider, VALUE, NewReal(val));
  1332.                     SetVar(theSlider, HIGHLIGHTED, NewInt(true));
  1333.                     Update(theReadout, val);
  1334.                     DrawMe(theSlider);
  1335.                     if (tracking) ChangedValue(theSlider);
  1336.                     curVal = val;
  1337.                     hilit = true;
  1338.                 }
  1339.             }
  1340.         }
  1341.     }
  1342.     }
  1343.     else
  1344.     {
  1345.     /* vertical orientation */
  1346.     if (style == SCROLL)
  1347.     {
  1348.         int wid = right - left;
  1349.     
  1350.         /* which part is mouse in? */
  1351.         if (mouseY > bottom && mouseY < bottom + wid) /* decr button */
  1352.         {
  1353.         /* track mouse */
  1354.         while (Mouse(&mX, &mY))
  1355.         {
  1356.             if (mX < left - SLOP || mX > right + SLOP
  1357.                 || mY < bottom - SLOP || mY > bottom + wid + SLOP)
  1358.             {
  1359.             /* outside slop rect */
  1360.             if (!hilit) continue;
  1361.             SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1362.             DrawMe(theSlider);
  1363.             hilit = false;
  1364.             }
  1365.             else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
  1366.             {
  1367.             /* decrement val by stepV */
  1368.             prevTime = times(&tbuf);
  1369.             if ((val -= stepV) < loV) val = loV;
  1370.             if (!hilit || val != curVal)
  1371.             {
  1372.                 SetVar(theSlider, VALUE, NewReal(val));
  1373.                 SetVar(theSlider, HIGHLIGHTED, NewInt(DECRHL));
  1374.                 DrawMe(theSlider);
  1375.                 if (tracking) ChangedValue(theSlider);
  1376.                 curVal = val;
  1377.                 hilit = true;
  1378.             }
  1379.             }
  1380.         }
  1381.         }
  1382.         else if (mouseY < top && mouseY > top-wid) /* incr button */
  1383.         {
  1384.         /* track mouse */
  1385.         while (Mouse(&mX, &mY))
  1386.         {
  1387.             if (mX < left - SLOP || mX > right + SLOP
  1388.                 || mY < top - wid - SLOP || mY > top + SLOP)
  1389.             {
  1390.             /* outside slop rect */
  1391.             if (!hilit) continue;
  1392.             SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1393.             DrawMe(theSlider);
  1394.             hilit = false;
  1395.             }
  1396.             else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
  1397.             {
  1398.             /* increment val by stepV */
  1399.             prevTime = times(&tbuf);
  1400.             if ((val += stepV) > hiV) val = hiV;
  1401.             if (!hilit || val != curVal)
  1402.             {
  1403.                 SetVar(theSlider, VALUE, NewReal(val));
  1404.                 SetVar(theSlider, HIGHLIGHTED, NewInt(INCRHL));
  1405.                 DrawMe(theSlider);
  1406.                 if (tracking) ChangedValue(theSlider);
  1407.                 curVal = val;
  1408.                 hilit = true;
  1409.             }
  1410.             }
  1411.         }
  1412.         }
  1413.         else /* in thumb or track */
  1414.         {
  1415.         ObjPtr thePorSh;
  1416.         real porSh, loC, hiC, siz, posn;
  1417.     
  1418.         thePorSh = GetRealVar("TrackSlider", theSlider, PORTIONSHOWN);
  1419.         if (thePorSh) porSh = GetReal(thePorSh);
  1420.         else return ObjTrue; /* Yow! Oh, well. */
  1421.         
  1422.         loC = bottom + wid + EDGE + SB_GAP;
  1423.         hiC = top - wid - EDGE - SB_GAP;
  1424.         /* normalize portion shown */
  1425.         porSh = porSh/(porSh + hiV - loV);
  1426.         siz = (hiC - loC)*porSh; /* size of thumb */
  1427.         if (siz < wid) siz = wid; /* minimum size */
  1428.         if (siz > hiC - loC) siz = hiC-loC; /* maximum size */
  1429.         hiC -= siz; /* upper limit of posn */
  1430.         if (hiV <= loV) posn = loC;
  1431.         else posn = (hiC - loC)*(val - loV)/(hiV - loV) + loC;
  1432.         if (mouseY < posn || mouseY > posn + siz) /* in track */
  1433.         {
  1434.             /* jump thumb to click position */
  1435.             offset = -siz/2;
  1436.             if (hiC <= loC)
  1437.             {
  1438.             val = loV;
  1439.             }
  1440.             else
  1441.             {
  1442.             val = loV + (hiV - loV)*(mouseY + offset - loC)/(hiC - loC);
  1443.             }
  1444.             if (val < loV) val = loV;
  1445.             else if (val > hiV) val = hiV;
  1446.             SetVar(theSlider, VALUE, NewReal(curVal = val));
  1447.         }
  1448.         else offset = posn - mouseY;
  1449.         SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
  1450.         DrawMe(theSlider);
  1451.         /* now follow mouse with thumb */
  1452.         while (Mouse(&mX, &mY))
  1453.         {
  1454.             if (mX < left - SLOP || mX > right + SLOP
  1455.                 || mY < bottom + wid - SLOP || mY > top - wid + SLOP)
  1456.             {
  1457.             /* outside slop rect */
  1458.             if (hilit)
  1459.             {
  1460.                 SetVar(theSlider, VALUE, theValue);
  1461.                 SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
  1462.                 DrawMe(theSlider);
  1463.                 if (tracking) ChangedValue(theSlider);
  1464.                 curVal = val = valSave;
  1465.                 hilit = false;
  1466.             }
  1467.             if (!Mouse(&mX, &mY)) break;
  1468.             }
  1469.             else
  1470.             {
  1471.             /* track mouse with thumb */
  1472.             if (hiC <= loC)
  1473.             {
  1474.                 val = loV;
  1475.             }
  1476.             else
  1477.             {
  1478.                 val = loV + (hiV - loV)*(mY + offset - loC)/(hiC - loC);
  1479.             }
  1480.             if (val < loV) val = loV;
  1481.             else if (val > hiV) val = hiV;
  1482.             if (!hilit || val != curVal)
  1483.             {
  1484.                 SetVar(theSlider, VALUE, NewReal(val));
  1485.                 SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
  1486.                 DrawMe(theSlider);
  1487.                 if (tracking) ChangedValue(theSlider);
  1488.                 curVal = val;
  1489.                 hilit = true;
  1490.             }
  1491.             }
  1492.         }
  1493.         }
  1494.     }
  1495.     else /* not a scrollbar */
  1496.     {
  1497.         if (style == SCALE || style == REVSCALE) /* adjust bounds */
  1498.         {
  1499.         bottom += VSCALEINSET - CTL_WID/2;
  1500.         top -= VSCALEINSET - CTL_WID/2;
  1501.         }
  1502.         cp = ((val - loV)/(hiV - loV))*(top - bottom - CTL_WID)
  1503.                 + bottom + CTL_WID/2 + 0.5;
  1504.         if (mouseY < cp - CTL_WID/2 - 1 || mouseY > cp + CTL_WID/2 + 1)
  1505.         {
  1506.         /* click in track; jump control to click position */
  1507.         offset = 0;
  1508.         val = loV + (hiV - loV)*
  1509.          (mouseY - bottom - CTL_WID/2)/(top - bottom - CTL_WID);
  1510.         if (val < loV) val = loV;
  1511.         else if (val > hiV) val = hiV;
  1512.         else if (stepV != 0.0)
  1513.         {
  1514.             int n;
  1515.             n = 0.5 + (val - loV)/stepV;
  1516.             val = loV + n*stepV;
  1517.         }
  1518.         if (flags & F_CONSTRAIN && (style == SCALE || style == REVSCALE)
  1519.             && lilStep != 0)
  1520.         {
  1521.             /* constrain value to little steps of scale */
  1522.             int n;
  1523.             n = 0.5 + val/lilStep;
  1524.             val = n*lilStep;
  1525.         }
  1526.         SetVar(theSlider, VALUE, NewReal(curVal = val));
  1527.         }
  1528.         else offset = cp - mouseY;
  1529.         /* now follow the mouse */
  1530.         while (Mouse(&mX, &mY))
  1531.         {
  1532.         if (mX < left - SLOP || mX > right + SLOP
  1533.             || mY < bottom - SLOP || mY > top + SLOP)
  1534.         {
  1535.             /* outside slop rect */
  1536.             if (hilit)
  1537.             {
  1538.             SetVar(theSlider, VALUE, theValue);
  1539.             SetVar(theSlider, HIGHLIGHTED, NewInt(false));
  1540.             Update(theReadout, valSave);
  1541.             DrawMe(theSlider);
  1542.             if (tracking) ChangedValue(theSlider);
  1543.             curVal = val = valSave;
  1544.             hilit = false;
  1545.             }
  1546.             if (!Mouse(&mX, &mY)) break;
  1547.         }
  1548.         else
  1549.         {
  1550.             /* follow mouse with slider */
  1551.             val = loV + (hiV - loV)*
  1552.               (mY + offset - bottom - CTL_WID/2)/(top - bottom - CTL_WID);
  1553.             if (val < loV) val = loV;
  1554.             else if (val > hiV) val = hiV;
  1555.             else if (stepV != 0.0)
  1556.             {
  1557.             int n;
  1558.             n = 0.5 + (val - loV)/stepV;
  1559.             val = loV + n*stepV;
  1560.             }
  1561.             else if (flags & F_CONSTRAIN && 
  1562.                 (style == SCALE || style == REVSCALE) && lilStep != 0)
  1563.             {
  1564.             /* constrain value to little steps of scale */
  1565.             int n;
  1566.             n = 0.5 + val/lilStep;
  1567.             val = n*lilStep;
  1568.             }
  1569.             if (!hilit || val != curVal)
  1570.             {
  1571.             SetVar(theSlider, VALUE, NewReal(val));
  1572.             SetVar(theSlider, HIGHLIGHTED, NewInt(true));
  1573.             Update(theReadout, val);
  1574.             DrawMe(theSlider);
  1575.             if (tracking) ChangedValue(theSlider);
  1576.             curVal = val;
  1577.             hilit = true;
  1578.             }
  1579.         }
  1580.         }
  1581.     }
  1582.     }
  1583.     SetVar(theSlider, HIGHLIGHTED, NewInt(false));
  1584.     DrawMe(theSlider);
  1585.     if (val != valSave)    /* value has changed */
  1586.     {
  1587.     Update(theReadout, val);
  1588.     ChangedValue(theSlider);
  1589.     LogControl(theSlider);
  1590.     }
  1591. #endif
  1592.     return ObjTrue;
  1593. }
  1594.